﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Microsoft.SharePoint.Client;
using System.Net;
using System.Security;
using System.IO;
using System.IO.Compression;

namespace Download2ZipWeb.Controllers
{
    public class DownloadController : Controller
    {
        // GET: Download
        public FileResult Index()
        {



            String SelectedItems = Request.QueryString["SelectedItems"];
            String[] listItemIds = SelectedItems.Split(',');
            List<ListItem> selectedListItems = new List<ListItem>();

            Guid listId = new Guid(Request.QueryString["ListId"]);

            var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);

            using (var clientContext = spContext.CreateUserClientContextForSPHost())
            {
                if (clientContext != null)
                {
                    List list = clientContext.Web.Lists.GetById(listId);

                    foreach (String listItemId in listItemIds)
                    {
                        ListItem listItem = list.GetItemById(int.Parse(listItemId));
                        selectedListItems.Add(listItem);

                    }

                    clientContext.ExecuteQuery();

                    MemoryStream ms = new MemoryStream();

                    ZipFileBuilder builder = new ZipFileBuilder(ms);

                    foreach (ListItem listItem in selectedListItems)
                    {
                        clientContext.Load(listItem);
                        clientContext.ExecuteQuery();


                        if (listItem.FileSystemObjectType == FileSystemObjectType.Folder)
                        {
                            AddFolder(clientContext, builder, listItem.Folder, string.Empty);

                        }
                        else if (listItem.FileSystemObjectType == FileSystemObjectType.File)
                        {
                            AddFile(clientContext, builder, listItem.File, string.Empty);
                        }
                    }

                    builder.Finish();

                    return new MemoryStreamFileResult(ms);

                }
            }


            return null;


        }

        private static void AddFile(ClientContext clientContext, ZipFileBuilder builder, Microsoft.SharePoint.Client.File file, string folder)
        {
            try
            {

                clientContext.Load(file);

                var streamFile = file.OpenBinaryStream();
                clientContext.Dispose();
                clientContext.ExecuteQuery();

                using (Stream stream = streamFile.Value)
                {
                    builder.Add(folder + "\\" + file.Name, stream);
                    stream.Close();
                }
            }
            catch (Exception)
            {

            }

        }

        private void AddFolder(ClientContext clientContext, ZipFileBuilder builder, Folder folder, string parentFolder)
        {
            clientContext.Load(folder);
            clientContext.Load(folder.Files);
            clientContext.Load(folder.Folders);
            clientContext.ExecuteQuery();

            string folderPath = parentFolder == string.Empty ? folder.Name : parentFolder + "\\" + folder.Name;
            builder.AddDirectory(folderPath);

            foreach (var file in folder.Files)
            {
                AddFile(clientContext, builder, file, folderPath);
            }

            foreach (var subFolder in folder.Folders)
            {
                AddFolder(clientContext, builder, subFolder, folderPath);
            }
        }


    }

    public class MemoryStreamFileResult : FileResult
    {
        private MemoryStream ms;
        public MemoryStreamFileResult(MemoryStream stream)
            : base("application/octet-stream")
        {
            ms = stream;
        }

        protected override void WriteFile(HttpResponseBase Response)
        {

            if (ms.Length > 0)
            {
                using (ms)
                {
                    string filename = "SelectedFiles.zip";
                    Response.Clear();
                    Response.ClearHeaders();
                    Response.ClearContent();
                    Response.AddHeader("Content-Length", ms.Length.ToString());
                    Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
                    Response.ContentType = "application/octet-stream";

                    byte[] buffer = new byte[65536];
                    ms.Position = 0;
                    int num;
                    do
                    {
                        num = ms.Read(buffer, 0, buffer.Length);
                        Response.OutputStream.Write(buffer, 0, num);
                    }

                    while (num > 0);

                    Response.Flush();
                }
            }

        }
    }

}